package top.tangyh.basic.spring_mvc.service.system.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.tangyh.basic.spring_mvc.database.mybatis.conditions.Wraps;
import top.tangyh.basic.spring_mvc.database.mybatis.conditions.query.LbQueryWrap;
import top.tangyh.basic.spring_mvc.service.SuperServiceImpl;
import top.tangyh.basic.spring_mvc.util.ArgumentAssert;
import top.tangyh.basic.spring_mvc.util.TreeUtil;
import top.tangyh.basic.spring_mvc.entity.BaseOrg;
import top.tangyh.basic.spring_mvc.manager.BaseOrgManager;
import top.tangyh.basic.spring_mvc.service.system.BaseOrgService;
import top.tangyh.basic.spring_mvc.vo.query.system.BaseOrgPageQuery;
import top.tangyh.basic.spring_mvc.vo.result.system.BaseOrgResultVO;
import top.tangyh.basic.spring_mvc.vo.save.system.BaseOrgSaveVO;
import top.tangyh.basic.spring_mvc.vo.update.system.BaseOrgUpdateVO;
import top.tangyh.basic.spring_mvc.constant.DefValConstants;

import java.util.*;

/**
 * <p>
 * 业务实现类
 * 组织
 * </p>
 *
 * @author CJ
 * @date 2021-10-18
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BaseOrgServiceImpl extends SuperServiceImpl<BaseOrgManager, Long, BaseOrg> implements BaseOrgService {
    private void fillOrg(BaseOrg org) {
        if (org.getParentId() == null || org.getParentId() <= 0) {
            org.setParentId(DefValConstants.PARENT_ID);
            org.setTreePath(DefValConstants.TREE_PATH_SPLIT);
            org.setTreeGrade(DefValConstants.TREE_GRADE);
        } else {
            BaseOrg parent = this.superManager.getById(org.getParentId());
            ArgumentAssert.notNull(parent, "请正确填写父级组织");
            org.setTreeGrade(parent.getTreeGrade() + 1);
            org.setTreePath(TreeUtil.getTreePath(parent.getTreePath(), parent.getId()));
        }
    }

    /**
     * 检查部门(整棵树)名称是否重复
     * @param name     机构名称
     * @param parentId 父ID
     * @param id       机构id
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public boolean check(String name, Long parentId, Long id) {
        ArgumentAssert.notEmpty(name, "请填写名称");
        LbQueryWrap<BaseOrg> wrap = Wraps.<BaseOrg>lbQ().eq(BaseOrg::getName, name).ne(BaseOrg::getId, id);
        return superManager.count(wrap) > 0;
    }

    @Override
    protected <SaveVO> BaseOrg saveBefore(SaveVO saveVO) {
        BaseOrgSaveVO baseOrgSaveVO = (BaseOrgSaveVO) saveVO;
        ArgumentAssert.isFalse(check(baseOrgSaveVO.getName(), baseOrgSaveVO.getParentId(), null), StrUtil.format("组织[{}]已经存在", baseOrgSaveVO.getName()));
        BaseOrg baseOrg = super.saveBefore(baseOrgSaveVO);
        fillOrg(baseOrg);
        return baseOrg;
    }

    @Override
    protected <UpdateVO> BaseOrg updateBefore(UpdateVO updateVO) {
        BaseOrgUpdateVO baseOrgUpdateVO = (BaseOrgUpdateVO) updateVO;
        ArgumentAssert.isFalse(check(baseOrgUpdateVO.getName(), baseOrgUpdateVO.getParentId(), baseOrgUpdateVO.getId()), StrUtil.format("组织[{}]已经存在", baseOrgUpdateVO.getName()));
        BaseOrg baseOrg = super.updateBefore(baseOrgUpdateVO);
        fillOrg(baseOrg);
        return baseOrg;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<Long> idList) {
        if (idList.isEmpty()) {
            return false;
        }
        boolean flag = superManager.removeByIds(idList);
        return flag;
    }

    @Override
    public List<BaseOrgResultVO> list(BaseOrgPageQuery query) {
        List<BaseOrg> list = superManager.list(Wraps.<BaseOrg>lbQ().like(BaseOrg::getName, query.getName()).eq(BaseOrg::getState, query.getState()).orderByAsc(BaseOrg::getSortValue));
        return BeanUtil.copyToList(list, BaseOrgResultVO.class);
    }


    @Override
    @Transactional(readOnly = true)
    public BaseOrg getCompanyByDeptId(Long deptId) {
        if (deptId == null) {
            return null;
        }
        BaseOrg org = superManager.getById(deptId);
        if (org == null) {
            return null;
        }
        if ("10".equals(org.getType())) {
            return org;
        }
        return getCompanyByDeptId(org.getParentId());
    }
}
